package com.example.zhangwei.util;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.example.zhangwei.Constants;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 * load image from url and add the images to cache 
 * <p>example:</p>
 * <p><blockquote><pre>
 * private AsyncImageLoader asyncImageLoader;//声明全局变量 
 * asyncImageLoader = new AsyncImageLoader();//在构造方法或者onCreate中初始化
 * Drawable cachedImage = asyncImageLoader.loadDrawable(url,new ImageCallback() {
 *		public void imageLoaded(Drawable imageDrawable, String imageUrl) {
 *			ImageView imageViewByTag = (ImageView) listView
 *					.findViewWithTag(imageUrl);
 *			if (imageViewByTag != null) {
 *				imageViewByTag.setImageDrawable(imageDrawable);
 *			}
 *		}
 *	});
 *    if (cachedImage == null) {
 *		holder.cover_img.setImageResource(R.drawable.reco_book_img);
 *	} else {
 *		holder.cover_img.setImageDrawable(cachedImage);
 *	}
 * </pre></blockquote>
 * </p>
 * @author dean
 * 
 */

@SuppressLint("NewApi")
public class AsyncImageLoader {
	final static String TAG = "AsyncImageLoader";
	private HashMap<String, SoftReference<Drawable>> picCache; 
	private final static File PIC_PATH= new File(Constants.path.IMAGE_DIR);
	private static BitmapFactory.Options opts = new BitmapFactory.Options();
	private ExecutorService executorService = Executors.newFixedThreadPool(4); 
	public int width;
	public int height;
//    private Context context;
    private float density;
	
	public AsyncImageLoader(Context context) {
//		this.context = context;
		density = context.getResources().getDisplayMetrics().density;
		picCache = new HashMap<String, SoftReference<Drawable>>();
		opts.inSampleSize = 1;
		opts.inPreferredConfig = Bitmap.Config.RGB_565;
	}
	
	public interface ImageCallback {
		public void imageLoaded(Drawable imageDrawable, String imageUrl);
	}

	@SuppressLint("HandlerLeak")
	public Drawable loadDrawable(final String picUrl,final ImageCallback imageCallback) {
		final String fileName = picUrl.substring(picUrl.lastIndexOf("/") + 1); 
		final String picUrlHashCode = picUrl.hashCode()+"";
		if (picCache.containsKey(picUrlHashCode)) {
			Drawable myDrawable = picCache.get(picUrlHashCode).get();
			if (myDrawable != null) {
				return myDrawable;
			}
		}
		final Handler handler = new Handler() {
			public void handleMessage(Message message) {
				imageCallback.imageLoaded((Drawable) message.obj, picUrl);
			}
		};
		executorService.submit(new Runnable() {
			
			public void run() {
				Drawable drawable = loadpicFromUrl(picUrl,fileName);
				if (drawable != null) {
					try{
					drawable = zoomDrawable(drawable,(int)(width*density),(int)(height*density));
					Log.e("width is ", "width is "+width+";height is "+height);
					}catch(OutOfMemoryError e){
					}
					picCache.put(picUrlHashCode, new SoftReference<Drawable>(drawable));
					handler.sendMessage(handler.obtainMessage(0, drawable));
				}
				drawable = null;
				
			}
		});
		return null;
	}

	@SuppressWarnings("deprecation")
	public  Drawable loadpicFromUrl(String url,String fileName) {
		Drawable drawable = null;
		fileName = url.hashCode()+"."+fileName
				.substring(fileName.lastIndexOf(".") + 1);
		if (!PIC_PATH.exists()) {
			PIC_PATH.mkdirs();
		}
		if (url == null || url.equals("")) {
		    return null;
		}
		File picFile=new File(PIC_PATH,fileName);
		if(picFile.exists()){
			Bitmap source = BitmapFactory.decodeFile(picFile.getPath(),opts);	
			if(source==null){
				return null;	
			}
			else{
				drawable= new BitmapDrawable(source);
			}
			
		}else{
			URL m;
			InputStream i = null;
			try {
				m = new URL(url);
				i = new BufferedInputStream((InputStream) m.getContent());
				BufferedInputStream inputStream =new BufferedInputStream((InputStream) m.getContent());
				saveImage(picFile, inputStream);
			} catch(FileNotFoundException e){
				return null;
			}catch (MalformedURLException e1) {
				return null;
			} catch (IOException e) {
			}catch (Exception e){
				return null;
			}

			try {
				drawable = Drawable.createFromStream(i, url);	
				
				if (i != null)
					i.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (OutOfMemoryError outOfMemoryError) {
				// arr = null;
				i = null;
				if (drawable != null) {
					drawable.setCallback(null);
					if (((BitmapDrawable) drawable).getBitmap() != null)
						((BitmapDrawable) drawable).getBitmap().recycle();
				}

				return null;
			}
		}
		return drawable;


	}
	private static void saveImage(File image, BufferedInputStream bis) {
		 if(image != null && image.getParentFile() != null){
			 image.getParentFile().mkdirs();
		    }
		FileOutputStream fos = null;    
	    int BUFFER_SIZE = 1024; 
	    byte[] buf = new byte[BUFFER_SIZE];    
	    int size = 0;    
	    try {
			fos = new FileOutputStream(image);
			 while ( (size = bis.read(buf)) != -1){     
			      fos.write(buf, 0, size); 
			 }   
		    fos.close();    
		    bis.close();    
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}    
	}
	public void shutDown(){
		executorService.shutdownNow();
	}
	
	private  Drawable zoomDrawable(Drawable drawable, int w, int h) {
		int width = drawable.getIntrinsicWidth();
		int height = drawable.getIntrinsicHeight();
		Bitmap oldbmp = drawableToBitmap(drawable);
		Matrix matrix = new Matrix();
		float scaleWidth = ((float) w / width);
		float scaleHeight = ((float) h / height);
		matrix.postScale(scaleWidth, scaleHeight);
		Bitmap newbmp = Bitmap.createBitmap(oldbmp, 0, 0, width, height,
				matrix, true);
		return new BitmapDrawable(null, newbmp);
	}

	private Bitmap drawableToBitmap(Drawable drawable) {
		int width = drawable.getIntrinsicWidth();
		int height = drawable.getIntrinsicHeight();
		Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
				: Bitmap.Config.RGB_565;
		Bitmap bitmap = Bitmap.createBitmap(width, height, config);
		Canvas canvas = new Canvas(bitmap);
		drawable.setBounds(0, 0, width, height);
		drawable.draw(canvas);
		return bitmap;
	}

}
